import Component from "../Component.js";
import DeviceTimerRefresh from "../shanxi/DeviceTimerRefresh.js"

import ServiceUtils from "../../experience/other/shanxi/ServiceUtils.js"
import {_toast} from "../../experience/utils/F7.js";
import Type from "../../experience/db/Type.js";

const Pointer = ol.interaction.Pointer
const Modify = ol.interaction.Modify;
const Point = ol.geom.Point;
const Feature = ol.Feature;
const Icon = ol.style.Icon;
const Style = ol.style.Style;
const Overlay = ol.Overlay;
// 沈阳院 那个项目编辑模式下的功能组件

// systemType与souceName的字典对应关系
const DEVICE_SOURCE_DICT = {
    0: Type.M_Station,
    1: Type.K_Station,
    2: Type.K_Node,
    3: Type.V_Camera
}

const RENDER_DEVIATE_DISTANCE = 800 // 设备位置渲染时候 允许多少半径内进行随机偏离
export default class DeviceEdit extends Component {
    constructor() {
        super();
    }

    template() {
        const div = `
            <div class="deviceTreeListBox" id="treelistbox">
                <ul id="ztreeinstance" class="ztree"></ul>
            </div>
        `

        const movingAlertPopup = `
            <div id="alertPopup" class="deviceDetail" style="width: 200px;height: 80px;line-height: 80px;padding-left: 20px">
                <span class="title">拖动设备以修改设备位置</span>
                <i class="fas fa-lightbulb"></i>
            </div>
        `
        this.$$("#article").append(movingAlertPopup);

        this.$$('body').append(div);
    }

    async control() {
        const refreshTimer = new DeviceTimerRefresh()
        this.ServiceUtils = new ServiceUtils()
        // 鼠标交互的自定义交互对象
        this.PointerInteraction = null
        // 添加 弹窗提示 气泡框
        const container = document.getElementById('alertPopup');
        this.movingAlertOverlay = new Overlay({
            element: container
        })
        this.movingAlertOverlay.setOffset([10,10])
        this.drawer.map.addOverlay(this.movingAlertOverlay);
        // 拖动状态的时候，监听 鼠标在map上的坐标位置
        this.DragCoordinate = [0, 0]
        this.setting = {
            edit: {
                enable: true,
                drag: {
                    isMove: false,
                    isCopy: true,
                    prev: false,
                    next: false,
                    inner: false
                },
                showRemoveBtn: false,
                showRenameBtn: false
            },
            callback: {
                beforeDrag: this.beforeDragFunc.bind(this),
                onDrop: this.dropFinish.bind(this),
                onClick: this.deviceTreeNodeClickCbFun.bind(this)
            },
            view: {
                fontCss: this.setFontTextColor,
                showIcon: false,
                showLine: false,
            }

        };
        this.personStationStorage = null
        this.sensorStationStorage = null
        this.camerasStorage = null
        // 返回的是完全符合树形结构的数据
        this.dataTreeLoadingOpen() // 先把loading打开
        const {m_station_list, k_station_list, cameraList} = await this.ServiceUtils.dataTreeFormat()
        // 根据实际情况 再进行额外结构处理
        const copy_m_station_list = []
        m_station_list.forEach((item) => {
            const tmp = {...item}
            delete tmp.children
            copy_m_station_list.push(tmp)
        })
        this.zNodes = [
            {
                name: "人员定位", isPos: true ,open: true, children: copy_m_station_list
            },
            {
                name: "安全监控", isPos: true,open: true, children: k_station_list
            },
            {
                name: "工业视频", isPos: true,open: true, children: cameraList
            }
        ];
        $(document).ready(() => {
            $.fn.zTree.init($("#ztreeinstance"), this.setting, this.zNodes);
            this.dataTreeLoadingClose()
        });

        // 刷新 目录树的数据状态
        this.emitter.on('device-tree-refresh', async () => {
            await this.ztreeRefresh()
        })

        this.emitter.on('device-pos-edit',async () => {
            const feature = this.emitter.params[0]
            this.app.dialog.confirm('是否移除该设备的位置信息','提示',this.deleteDevicePos(feature))
        })

        // 直接打开 modify交互
        this.initModifyAction()
        // hover设备元素时允许弹窗 提醒。
        this.drawer.map.on('pointermove', this.feature_popup.bind(this));
    }

    // 气泡弹窗提示
    feature_popup(pixelInstance, properties) {
        const pixel = pixelInstance.pixel
        const feature = this.drawer.map.forEachFeatureAtPixel(pixel, feature => feature)
        if (feature) {
            if (!properties) {  // 如果没传值，则表示为点击事件
                if (!feature.get('device_id')) return this.movingAlertOverlay.setPosition(undefined);
            }
            this.movingAlertOverlay.setPosition(this.drawer.map.getCoordinateFromPixel(pixel));

        } else {
            this.movingAlertOverlay.setPosition(undefined);
        }
    }

    // 初始化 modify交互
    initModifyAction() {
        const commonStyle = new Style({
            image: new Icon({
                src: 'assets/images/shanxi/touming.svg',
                scale: 0.1
            })
        })

        const mStationSource = this.drawer.source(Type.M_Station)
        const kStationSource = this.drawer.source(Type.K_Station)
        const kNodeSource = this.drawer.source(Type.K_Node)
        const vCameraSource = this.drawer.source(Type.V_Camera)
        // 不同图层的 modify交互对象
        const mStationModifyInterAction = new Modify({
            source: mStationSource,
            style: commonStyle
        })
        const kStationModifyInterAction = new Modify({
            source: kStationSource,
            style: commonStyle
        })
        const kNodeModifyInterAction = new Modify({
            source: kNodeSource,
            style: commonStyle
        })
        const vCameraModifyInterAction = new Modify({
            source: vCameraSource,
            style: commonStyle
        })
        const InterActionArr = [mStationModifyInterAction,kStationModifyInterAction,kNodeModifyInterAction,vCameraModifyInterAction]
        InterActionArr.forEach((interAction) => {
            interAction.on('modifyend',async (event) => {
                const movedFeatures = event.features.getArray()
                const currentFeature = movedFeatures[0]
                const deviceId = currentFeature.get('device_id')
                const sub1 = currentFeature.get('sub1')
                const coordinate = currentFeature.getGeometry().getCoordinates()
                const denormalCoordinate = [this.algo.denormalX(coordinate[0]),this.algo.denormalY(coordinate[1])]
                const deviceNodes = [{
                    device_id: deviceId,
                    sub1,
                    Coordinate: denormalCoordinate
                }]
                const current_metaId = this.utils.getUrlParamer('meta_id')
                const new_device_res = await this.api.shanxiDevicePosUpdate(deviceNodes, current_metaId)
                if(new_device_res.code == 0) {
                    _toast('设备位置修改成功')
                }
                await this.db.refresh('device', new_device_res.data)
                // 然后 重新渲染 设备位置
                await this.refreshDevicePos()
            })
            this.drawer.addInteraction(interAction)
        })
    }

    // 触发节点拖动之前，判断节点是否能被拖动
    beforeDragFunc(treeId, treeNodes) {
        const dragNode = treeNodes[0]
        if (dragNode.name == '人员定位' || dragNode.name == '安全监控' || dragNode.name == '工业视频') {
            return false
        } else {
            this.PointerInteraction = new Pointer({
                handleMoveEvent: (event) => {
                    this.DragCoordinate = event.coordinate
                }
            })
            this.drawer.addInteraction(this.PointerInteraction)
        }
    }

    // 节点拖动结束 触发函数
    async dropFinish(event, treeId, treeNodes) {
        this.drawer.removeInteraction(this.PointerInteraction)
        // 先获取下 当前矿下的所有的设备的位置信息
        const current_metaId = this.utils.getUrlParamer('meta_id')
        const {data: rdata} = await this.api.shanxiDevicePosGet(current_metaId)
        const {device_pos_infos: current_devices_pos} = rdata
        const dragNode = treeNodes[0]
        let submitNodes = []
        if (dragNode.children) {
            // 拖动的是监控分站。修改位置的就应该是多个设备
            const devices = [dragNode, ...dragNode.children]
            for (let i = 0; i < devices.length; i++) {
                const node = {
                    meta_id: devices[i].MineID,
                    device_id: devices[i].NodeID ?? devices[i].StationID,
                    sub1: devices[i].systemType,
                    name: devices[i].StationPlace ?? devices[i].NodePlace ?? devices[i].name
                }
                if (i == 0) {
                    // 把准确的位置给到监控分站
                    node.Coordinate = [this.algo.denormalX(this.DragCoordinate[0]), this.algo.denormalY(this.DragCoordinate[1])]
                } else {
                    // 其余的传感器 在指定半径范围内，随机分布
                    node.Coordinate = this.ServiceUtils.enablePosDeviate(this.DragCoordinate, RENDER_DEVIATE_DISTANCE)
                }
                submitNodes.push(node)
            }
        } else {
            // 拖动的是人员分站，传感器或者工业视频设备
            submitNodes = [
                {
                    meta_id: dragNode.MineID ?? dragNode.MineId ?? dragNode.mineId,
                    device_id: dragNode.cameraIndexCode ?? dragNode.NodeID ?? dragNode.StationId,
                    Coordinate: [this.algo.denormalX(this.DragCoordinate[0]), this.algo.denormalY(this.DragCoordinate[1])],
                    sub1: dragNode.systemType,
                    name: dragNode.StationName ?? dragNode.NodePlace ?? dragNode.name
                }
            ]
        }
        submitNodes.forEach(n => {
            const flag = current_devices_pos.some((p) => {
                return p.device_id == n.device_id && p.sub1 == n.sub1
            })
            if (flag) {
                n.isExist = true
            } else {
                n.isExist = false
            }
        })
        // 分离 要提交的nodes
        const ExistDeviceNodes = [] // 里面都是仅需要被修改位置的node
        const NotExistDeviceNodes = [] // 里面是需要被新添加到device表的node
        submitNodes.forEach((node) => {
            if (node.isExist) {
                ExistDeviceNodes.push(node)
            } else {
                NotExistDeviceNodes.push(node)
            }
        })
        let new_device_res = null
        if (ExistDeviceNodes.length > 0) {
            // 提交位置修改请求
            new_device_res = await this.api.shanxiDevicePosUpdate(ExistDeviceNodes, current_metaId)
            if(new_device_res.code == 0) {
                _toast('设备位置修改成功')
            }
        }
        if (NotExistDeviceNodes.length > 0) {
            // 提交位置新增请求
            new_device_res = await this.api.shanxiDevicePosPost(NotExistDeviceNodes, current_metaId)
            if(new_device_res.code == 0) {
                _toast('位置新增成功')
            }
        }
        // 每次完成device位置更新之后，就将本地indexDb中的device进行更新。
        await this.db.refresh('device', new_device_res.data)
        // 然后 重新渲染 设备位置
        await this.refreshDevicePos()
        await this.ztreeRefresh()
    }

    // 重新渲染 设备位置
    async refreshDevicePos() {
        await this.drawer._Shanxi_Device_kStation()
        await this.drawer._Shanxi_Device_mStation()
        await this.drawer._Shanxi_Device_kNode()
        await this.drawer._Shanxi_Device_vCamera()
    }

    setFontTextColor(treeId, treeNode) {
        if(treeNode.level == 0) {
            return {color: "white"}
        }
        return treeNode.isPos ? {color: "green"} : {color: "red"};
    }

    // 控制目录树loading的打开
    dataTreeLoadingOpen() {
        const loadingImg = document.createElement('div')
        loadingImg.innerHTML = '<img src="assets/images/shanxi/loading.gif" />'
        loadingImg.style.width = '60px'
        loadingImg.style.height = '60px'
        loadingImg.style.marginLeft = 'auto'
        loadingImg.style.marginRight = 'auto'
        this.$$('#treelistbox').prepend(loadingImg)
        this.dataTreeLoadImg = loadingImg
    }

    // 控制目录树loading的关闭
    dataTreeLoadingClose() {
        try {
            this.dataTreeLoadImg.remove()
        }
        catch (e) {
            console.error('不能在没有开启loading图片时，关闭loading')
        }
    }

    async ztreeRefresh() {
        const {m_station_list, k_station_list, cameraList} = await this.ServiceUtils.dataTreeFormat()
        const copy_m_station_list = []
        m_station_list.forEach((item) => {
            const tmp = {...item}
            delete tmp.children
            copy_m_station_list.push(tmp)
        })
        this.zNodes = [
            {
                name: "人员定位", isPos: true ,open: true, children: copy_m_station_list
            },
            {
                name: "安全监控", isPos: true , open: true, children: k_station_list
            },
            {
                name: "工业视频", isPos: true ,open: true, children: cameraList
            }
        ];
        $.fn.zTree.init($("#ztreeinstance"), this.setting, this.zNodes);
    }

    // 选择删除 设备位置的函数
    deleteDevicePos(feature) {
        const currentFeature = feature
        return async () => {
            const current_metaId = this.utils.getUrlParamer('meta_id')
            const deviceId = currentFeature.get('device_id')
            const deviceType = currentFeature.get('type')
            let result
            if(deviceType == 'k_station') {
                // 如果 设备类型是监控分站的话，应该把分站下的测点的位置也一起删除掉
                const kStations = this.zNodes[1].children
                const enableKstation = kStations.find((station) => {
                    // console.log('station.stationID=',station.stationID)
                    // console.log('deviceId=',deviceId)
                    // console.log(station.stationID == deviceId)
                    return station.StationID == deviceId
                })
                const postArr = []
                postArr.push({
                    device_id : enableKstation.StationID,
                    device_type: deviceType,
                })
                enableKstation.children.forEach((node) => {
                    postArr.push({
                        device_id : node.NodeID,
                        device_type: 'k_node',
                    })
                })
                const { data } = await this.api.shanxiDevicePosDelete(postArr,current_metaId)
                result = data
            }
            else {
                const objs = [{
                    device_id : deviceId,
                    device_type: deviceType,
                }]
                const { data } = await this.api.shanxiDevicePosDelete(objs,current_metaId)
                result = data
            }
            // 把本地的 device进行更新
            await this.db.refresh('device',result)
            await this.drawer.shanxi_device_refresh()
            await this.ztreeRefresh()
        }
    }


    // 目录树 触发设备点击。
    deviceTreeNodeClickCbFun(event,treeId,treeNode) {
        console.log('treeNode', treeNode)
        if(treeNode.level == 0) {
            // 第一层级 直接跳过
            return
        }
        const sourceName = DEVICE_SOURCE_DICT[treeNode.systemType]
        const device_id = treeNode.cameraIndexCode ?? treeNode.NodeID ?? treeNode.StationID ?? treeNode.StationId
        this.deviceLocate(device_id, sourceName)
    }

    // 设备定位
    deviceLocate(deviceId, sourceName) {
        const source = this.drawer.source(sourceName)
        const features = source.getFeatures()
        const targetFeature = features.find((f) => {
            return f.get('device_id') == deviceId
        })
        try {
            const coordinate = targetFeature.getGeometry().getCoordinates()
            this.drawer.map.getView().setCenter(coordinate);
            // 创建一个临时的矩形框 标记出 当前的view中心
            const tmpImg = new Icon({
                src: 'assets/images/shanxi/rectangle.png',
                scale: 0.25
            })
            const recStyle = new Style({
                image: tmpImg
            })
            const rectangleFeature = new Feature()
            rectangleFeature.setGeometry(new Point(coordinate))
            rectangleFeature.setStyle(recStyle)
            source.addFeature(rectangleFeature)
            const tmpTimer = setTimeout(() => {
                source.removeFeature(rectangleFeature)
                clearTimeout(tmpTimer)
            },1500)
            return true
        }
        catch (e) {
            _toast('当前分站或设备还没有被添加位置，请先添加位置')
            return false
        }
    }

}